package kr.ac.kaist.idb.csnql.clause;

import java.io.Serializable;
import java.util.Hashtable;

/**
 * @brief Class for calculation of operations, constants, and custom function
 * @author Jongheon Park (korex527@kaist.ac.kr)
 */
public class SNQLUtils implements Serializable
{
    
    /**
	 * @brief Serial version UID which is automatically generated
	 */
	private static final long serialVersionUID = 741758859708158245L;

	/** @brief Static tabke for custom functions */
    private static Hashtable<String, Integer> fcts_ = null;
    
    /** @brief The Constant VARIABLE_PLIST. */
    public static final int VARIABLE_PLIST = 10000;

    /**
     * @brief Instantiates a new SNQLUtils.
     */
    public SNQLUtils()
    {
    }

    /**
     * @brief Add the custom function
     *
     * @param s The function name
     * @param i The index
     */
    public static void addCustomFunction(String s, int i)
    {
        if(fcts_ == null)
            fcts_ = new Hashtable<String, Integer>();
        
        if(i <= 0)
            i = 1;
        
        fcts_.put(s.toUpperCase(), new Integer(i));
    }

    /**
     * @brief Checks if there is custom function
     *
     * @param s The custom function
     * @return The index integer
     */
    public static int isCustomFunction(String s)
    {
        Integer integer;
        
        if(s == null || s.length() < 1 || fcts_ == null || (integer = (Integer)fcts_.get(s.toUpperCase())) == null)
            return -1;
        else
            return integer.intValue();
    }

    /**
     * @brief Checks if input string is aggregation function.
     *
     * @param s The custom function
     * @return true, if input string is aggregation function.
     */
    public static boolean isAggregate(String s)
    {
        s = s.toUpperCase().trim();
        return s.equals("SUM") || s.equals("AVG") || s.equals("MAX") || s.equals("MIN") || s.equals("COUNT") || fcts_ != null && fcts_.get(s) != null;
    }

    /**
     * @param s the function string
     * @return The aggregate function
     * @brief Get the aggregate function
     */
    public static String getAggregateCall(String s)
    {
        int i = s.indexOf(40);
        
        if(i <= 0)
            return null;
        
        String s1 = s.substring(0, i);
        
        if(isAggregate(s1))
            return s1.trim();
        else
            return null;
    }
    
    /**
     * @param timeVar The time string
     * @return The time (long type)
     * @brief Get the time (long type)
     */
    public static long getTimeToLong(String timeVar)
	{
		long mTime;
		char time_unit;
		int time;
		time_unit = timeVar.charAt(timeVar.length()-1);
		
		if(isIntNumber(timeVar))
		{
			if(Integer.parseInt(timeVar) < 0)
				return 0;
			else
				return Math.round(Long.parseLong(timeVar));
		}
		else
		{
			time = Integer.parseInt(timeVar.substring(0, timeVar.length()-1));
			
			//["s","m","h","D","M","Y"] 
			if( time_unit == 's')
			{
				mTime = time;
				return Math.round(mTime* 1000);
			}
			else if( time_unit == 'm')
			{
				mTime = 60*time;
				return Math.round(mTime* 1000);
			}
			else if (time_unit == 'h')
			{	
				mTime = 3600*time;
				return Math.round(mTime* 1000);
			}
			else if (time_unit == 'D')
			{
				mTime = 24*3600*time;
				return Math.round(mTime* 1000);
			}
			else if (time_unit == 'M')
			{
				mTime = 30*24*3600*time;
				return Math.round(mTime* 1000);
			}
			else if (time_unit == 'Y')
			{
				mTime = 365*24*3600*time;
				return Math.round(mTime* 1000);
			}
			
			return -1;
		}
	}
    
    /**
     * @param num the number string
     * @return true, if it is integer number
     * @brief Checks if it is integer number.
     */
    private static boolean isIntNumber(String num){
        try{
            Integer.parseInt(num);
        } catch(NumberFormatException nfe) {
            return false;
        }
        return true;
    }
}
